/**
 * Copyright (c) 2022 Beijing Jiaotong University
 * PhotLab is licensed under [Open Source License].
 * You can use this software according to the terms and conditions of the [Open Source License].
 * You may obtain a copy of [Open Source License] at: [https://open.source.license/]
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *
 * See the [Open Source License] for more details.
 *
 * Author: Qing'ao Zhang, Jiang Long, Zhenjie Wei
 * Created: Aug. 2, 2023
 * Supported by: National Key Research and Development Program of China
 */

import {
    PhotDetector,
    PhotGrid,
    PhotSource,
    PhotMaterial,
    PhotMaterialProperty,
    PhotWaveguide,
    PhotFigure
} from "../thrift/gen-nodejs/device_data_type_types"
import thriftClient from "../utils/conn"
import service from "../thrift/gen-nodejs/Device"


export default class DeviceService {
    private _client: any
    constructor(socket: [string, number]) {
        this._client = thriftClient(service, socket[0], socket[1])
    }

    public async openGrid(gridPath: string): Promise<PhotGrid> {
        return await this._client.open_grid(gridPath)
    }

    public async closeGrid(gridId: number): Promise<PhotGrid> {
        return await this._client.close_grid(gridId)
    }

    public async saveGrid(gridId: number) {
        return await this._client.save_grid(gridId)
    }

    public async saveGridAs(gridId: number, filePath: string) {
        return await this._client.save_grid_as(gridId, filePath)
    }

    public async addGrid(grid: PhotGrid): Promise<PhotGrid> {
        return await this._client.add_grid(grid)
    }

    /**
     * Add a light source to the simulation grid.
     * @param gridId The id of the grid to add the source to.
     * @param source The source to add.
     * @returns null
     */
    public async addSource(gridId: number, source: PhotSource): Promise<PhotSource> {
        return await this._client.add_source(gridId, source)
    }

    public async addWaveguide(gridId: number, waveguide: PhotWaveguide): Promise<PhotWaveguide> {
        return await this._client.add_waveguide(gridId, waveguide)
    }

    public async addMaterial(material: PhotMaterial): Promise<PhotMaterial> {
        return await this._client.add_material(material)
    }

    public async addDetector(gridId: number, detector: PhotDetector): Promise<PhotDetector> {
        return await this._client.add_detector(gridId, detector)
    }

    public async getGrid(gridId: number): Promise<PhotGrid> {
        return await this._client.get_grid(gridId)
    }

    /**
     * Get an existing light source from the simulation grid.
     * @param gridId The id of the grid.
     * @param sourceId The id of the source.
     * @returns The source:PhotSource.
     */
    public async getSource(gridId: number, sourceId: number): Promise<PhotSource> {
        return await this._client.get_source(gridId, sourceId)
    }

    public async getWaveguide(gridId: number, waveguideId: number): Promise<PhotWaveguide> {
        return await this._client.get_waveguide(gridId, waveguideId)
    }

    public async getWaveguideDefaultParameterList(name: string): Promise<string> {
        return await this._client.get_waveguide_default_parameter_list(name)
    }

    public async getAllWaveguideDefaultParameterList(): Promise<string> {
        return await this._client.get_all_waveguide_default_parameter_list()
    }

    public async getMaterial(materialName: string): Promise<PhotMaterial> {
        return await this._client.get_material(materialName)
    }

    public async getMaterials(): Promise<PhotMaterial[]> {
        return await this._client.get_materials()
    }

    public async getDetector(gridId: number, detectorId: number): Promise<PhotDetector> {
        return await this._client.get_detector(gridId, detectorId)
    }

    public async getFigure(gridId: number, axis: string, axisIndex: number, figureType: string): Promise<PhotFigure> {
        return await this._client.get_figure(gridId, axis, axisIndex, figureType)
    }

    public async getFigures(gridId: number, axisIndex: number[], figureType: string): Promise<PhotFigure[]> {
        return await this._client.get_figures(gridId, axisIndex, figureType)
    }

    public async updateGrid(grid: PhotGrid) {
        return await this._client.update_grid(grid)
    }

    /**
     * Update a light source in a simulated grid.
     * @param gridId The id of the grid to update the source in.
     * @param source The source to update.
     * @returns null
     */
    public async updateSource(gridId: number, source: PhotSource) {
        return await this._client.update_source(gridId, source)
    }

    public async updateWaveguide(gridId: number, waveguide: PhotWaveguide) {
        return await this._client.update_waveguide(gridId, waveguide)
    }

    public async updateMaterial(materialName: string, material: PhotMaterial) {
        return await this._client.update_material(materialName, material)
    }

    public async updateMaterialProperty(materialName: string, propertyId: number, property: PhotMaterialProperty) {
        return await this._client.update_material_property(materialName, propertyId, property)
    }

    public async updateDetector(gridId: number, detector: PhotDetector) {
        return await this._client.update_detector(gridId, detector)
    }

    public async deleteGrid(gridId: number) {
        return await this._client.delete_grid(gridId)
    }

    /**
     * Removes a light source in the simulation grid.
     * @param gridId The id of the grid.
     * @param sourceId The id of the source.
     * @returns null
     */
    public async deleteSource(gridId: number, sourceId: number) {
        return await this._client.delete_source(gridId, sourceId)
    }

    public async deleteWaveguide(gridId: number, waveguideId: number) {
        return await this._client.delete_waveguide(gridId, waveguideId)
    }

    public async deleteMaterial(materialName: string) {
        return await this._client.delete_material(materialName)
    }

    public async deleteMaterialProperty(materialName: string, propertyId: number) {
        return await this._client.delete_material_property(materialName, propertyId)
    }

    public async deleteDetector(gridId: number, detectorId: number) {
        return await this._client.delete_detector(gridId, detectorId)
    }

    public async saveMaterial(material: PhotMaterial) {
        return await this._client.save_material(material)
    }

    public async saveFigureAs(gridId: number, axis: string, axisIndex: number, filePath: string, figureType: string) {
        return await this._client.save_figure_as(gridId, axis, axisIndex, filePath, figureType)
    }

    public async run(gridId: number) {
        return await this._client.run(gridId)
    }

}